#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 5;
const double INF = 1e-16;
struct Segment {
	double l, r;
} Seg[maxn];
int n, m, maxl, maxv, Testnum, cnt, ans1, ans2;
double d[maxn], v[maxn], a[maxn], used[maxn];
double pos[maxn];
bool exist[maxn], vis[maxn];
vector <int> Covered[maxn];
inline int read () {
	int x = 0, k = 1;
	char ch = getchar ();
	while (!isdigit (ch) && ch != '-') ch = getchar ();
	if (ch == '-') {
		k = -1;
		ch = getchar ();
	}
	while (isdigit (ch)) {
		x = x * 10 + ch - '0';
		ch = getchar ();
	}
	return x * k;
} 
inline bool cmp (Segment x, Segment y) {
	return ((x.l != y.l) ? (x.l < y.l) : (x.r < y.r));
}
inline bool cmp1 (vector <int> x, vector <int> y) {
	return x.size () < y.size ();
}
int main () {
	freopen ("detect.in", "r", stdin);
	freopen ("detect.out", "w", stdout);
	Testnum = read ();
	while (Testnum--){
		memset (used, 0, sizeof (used));
		memset (exist, false, sizeof (exist));
		memset (vis, false, sizeof (vis));
		for (int i = 1; i <= cnt; i++) Seg[i].l = Seg[i].r = 0;
		for (int i = 1; i <= m; i++) Covered[i].clear ();
		cnt = ans1 = ans2 = 0;
		n = read (), m = read (), maxl = read (), maxv = read ();
		for (int i = 1; i <= n; i++) {
			d[i] = read (), v[i] = read (), a[i] = read ();
			double curl = 0, curr = 0;
			if (v[i] <= maxv && a[i] <= 0) continue;
			if (v[i] > maxv) {
				curl = d[i];
				if (a[i] < 0) 
				curr = min(d[i] + (double) (maxv * maxv - v[i] * v[i]) / (2.0 * a[i]) - INF, (double)maxl);
				else curr = maxl;
				Seg[++cnt] = (Segment) {curl, curr};
			} else {
				curl = d[i] + (double) (maxv * maxv - v[i] * v[i]) / (2.0 * a[i]) + INF;
				if (curl > maxl) continue;
				curr = maxl;
				Seg[++cnt] = (Segment) {curl, curr};
			}
		}
		for (int i = 1; i <= m; i++) pos[i] = read ();
		sort (pos + 1, pos + 1 + m);
		sort (Seg + 1, Seg + 1 + cnt, cmp);
		for (int i = 1; i <= cnt; i++) {
			double posl, posr;
			posl = Seg[i].l; posr = Seg[i].r;
			int pos1 = lower_bound (pos + 1, pos + 1 + m, posl) - pos;
			int pos2 = upper_bound (pos + 1, pos + 1 + m, posr) - pos - 1;
			if (pos1 <= pos2) ans1++, exist[i] = 1;
		}
		printf ("%d ", ans1);
		for (int i = 1; i <= cnt; i++) {
			if (!exist[i]) continue;
			double posl = Seg[i].l, posr = Seg[i].r;
			int st = lower_bound (pos + 1, pos + 1 + m, posl) - pos;
			int ed = upper_bound (pos + 1, pos + 1 + m, posr) - pos - 1;
			for (int j = st; j <= ed; j++) Covered[j].push_back (i), used[i]++;
		}
		sort (Covered + 1, Covered + 1 + m, cmp1);
		for (int i = 1; i <= m; i++) {
			if (Covered[i].size () == 0) {
				ans2++;
				continue;
			}
			bool flag = 1;
			for (int x : Covered[i]) if (used[x] == 1) flag = 0;
			if (!flag) continue;
			ans2++;
			for (int x : Covered[i]) used[x]--;
		}
		printf ("%d\n", ans2);
	}
	return 0;
}
